import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor, StreamableFile } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ClassTransformOptions, instanceToPlain } from 'class-transformer';
import { Observable, map } from 'rxjs';
import { CLASS_SERIALIZER_OPTIONS } from './serizalize-options.decorator';
import { isObject } from 'class-validator';


@Injectable()
export class ClassSerializerInterceptor2 implements NestInterceptor {

  @Inject(Reflector)
  protected readonly reflector: Reflector

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const contextOptions = this.getContextOptions(context)
    return next.handle().pipe(map((res) => this.serialize(res, contextOptions)));
  }

  serialize(response: Record<string, any> | Array<Record<string, any>>, options: ClassTransformOptions) {
    if(response instanceof StreamableFile) {
      return response
    }
    return Array.isArray(response) ? response.map(item => this.transformToNewPlain(item, options)) : this.transformToNewPlain(response, options)
  }

  transformToNewPlain(plain: any, options: ClassTransformOptions) {
    if (!plain) {
      return plain
    }
    return instanceToPlain(plain, options)
  }

  protected getContextOptions(context: ExecutionContext): ClassTransformOptions | undefined {
    return this.reflector.getAllAndOverride(CLASS_SERIALIZER_OPTIONS, [
      context.getHandler(),
      context.getClass()
    ])
  }
}
